1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package com.sun.crypto.provider;
27
28 import java.util.Arrays;
29
30 import java.security.*;
31 import java.security.spec.AlgorithmParameterSpec;
32
33 import javax.crypto.*;
34 import javax.crypto.spec.SecretKeySpec;
35
36 import sun.security.internal.spec.TlsPrfParameterSpec;
37
38
39
40
41
42
43
44
45
46
47
48 abstract class TlsPrfGenerator extends KeyGeneratorSpi {
49
50
51
52
53 private final static byte[] B0 = new byte[0];
54
55 final static byte[] LABEL_MASTER_SECRET =
56 { 109, 97, 115, 116, 101, 114, 32, 115, 101, 99, 114, 101, 116 };
57
58 final static byte[] LABEL_KEY_EXPANSION =
59 { 107, 101, 121, 32, 101, 120, 112, 97, 110, 115, 105, 111, 110 };
60
61 final static byte[] LABEL_CLIENT_WRITE_KEY =
62 { 99, 108, 105, 101, 110, 116, 32, 119, 114, 105, 116, 101, 32,
63 107, 101, 121 };
64
65 final static byte[] LABEL_SERVER_WRITE_KEY =
66 { 115, 101, 114, 118, 101, 114, 32, 119, 114, 105, 116, 101, 32,
67 107, 101, 121 };
68
69 final static byte[] LABEL_IV_BLOCK =
70 { 73, 86, 32, 98, 108, 111, 99, 107 };
71
72
73
74
75
76 private static final byte[] HMAC_ipad64 = genPad((byte)0x36, 64);
77 private static final byte[] HMAC_ipad128 = genPad((byte)0x36, 128);
78 private static final byte[] HMAC_opad64 = genPad((byte)0x5c, 64);
79 private static final byte[] HMAC_opad128 = genPad((byte)0x5c, 128);
80
81
82 final static byte[][] SSL3_CONST = genConst();
83
84 static byte[] genPad(byte b, int count) {
85 byte[] padding = new byte[count];
86 Arrays.fill(padding, b);
87 return padding;
88 }
89
90 static byte[] concat(byte[] b1, byte[] b2) {
91 int n1 = b1.length;
92 int n2 = b2.length;
93 byte[] b = new byte[n1 + n2];
94 System.arraycopy(b1, 0, b, 0, n1);
95 System.arraycopy(b2, 0, b, n1, n2);
96 return b;
97 }
98
99 private static byte[][] genConst() {
100 int n = 10;
101 byte[][] arr = new byte[n][];
102 for (int i = 0; i < n; i++) {
103 byte[] b = new byte[i + 1];
104 Arrays.fill(b, (byte)('A' + i));
105 arr[i] = b;
106 }
107 return arr;
108 }
109
110
111
112 private final static String MSG = "TlsPrfGenerator must be "
113 + "initialized using a TlsPrfParameterSpec";
114
115 private TlsPrfParameterSpec spec;
116
117 public TlsPrfGenerator() {
118 }
119
120 protected void engineInit(SecureRandom random) {
121 throw new InvalidParameterException(MSG);
122 }
123
124 protected void engineInit(AlgorithmParameterSpec params,
125 SecureRandom random) throws InvalidAlgorithmParameterException {
126 if (params instanceof TlsPrfParameterSpec == false) {
127 throw new InvalidAlgorithmParameterException(MSG);
128 }
129 this.spec = (TlsPrfParameterSpec)params;
130 SecretKey key = spec.getSecret();
131 if ((key != null) && ("RAW".equals(key.getFormat()) == false)) {
132 throw new InvalidAlgorithmParameterException(
133 "Key encoding format must be RAW");
134 }
135 }
136
137 protected void engineInit(int keysize, SecureRandom random) {
138 throw new InvalidParameterException(MSG);
139 }
140
141 SecretKey engineGenerateKey0(boolean tls12) {
142 if (spec == null) {
143 throw new IllegalStateException(
144 "TlsPrfGenerator must be initialized");
145 }
146 SecretKey key = spec.getSecret();
147 byte[] secret = (key == null) ? null : key.getEncoded();
148 try {
149 byte[] labelBytes = spec.getLabel().getBytes("UTF8");
150 int n = spec.getOutputLength();
151 byte[] prfBytes = (tls12 ?
152 doTLS12PRF(secret, labelBytes, spec.getSeed(), n,
153 spec.getPRFHashAlg(), spec.getPRFHashLength(),
154 spec.getPRFBlockSize()) :
155 doTLS10PRF(secret, labelBytes, spec.getSeed(), n));
156 return new SecretKeySpec(prfBytes, "TlsPrf");
157 } catch (GeneralSecurityException e) {
158 throw new ProviderException("Could not generate PRF", e);
159 } catch (java.io.UnsupportedEncodingException e) {
160 throw new ProviderException("Could not generate PRF", e);
161 }
162 }
163
164 static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
165 byte[] seed, int outputLength,
166 String prfHash, int prfHashLength, int prfBlockSize)
167 throws NoSuchAlgorithmException, DigestException {
168 if (prfHash == null) {
169 throw new NoSuchAlgorithmException("Unspecified PRF algorithm");
170 }
171 MessageDigest prfMD = MessageDigest.getInstance(prfHash);
172 return doTLS12PRF(secret, labelBytes, seed, outputLength,
173 prfMD, prfHashLength, prfBlockSize);
174 }
175
176 static byte[] doTLS12PRF(byte[] secret, byte[] labelBytes,
177 byte[] seed, int outputLength,
178 MessageDigest mdPRF, int mdPRFLen, int mdPRFBlockSize)
179 throws DigestException {
180
181 if (secret == null) {
182 secret = B0;
183 }
184
185
186 if (secret.length > mdPRFBlockSize) {
187 secret = mdPRF.digest(secret);
188 }
189
190 byte[] output = new byte[outputLength];
191 byte [] ipad;
192 byte [] opad;
193
194 switch (mdPRFBlockSize) {
195 case 64:
196 ipad = HMAC_ipad64.clone();
197 opad = HMAC_opad64.clone();
198 break;
199 case 128:
200 ipad = HMAC_ipad128.clone();
201 opad = HMAC_opad128.clone();
202 break;
203 default:
204 throw new DigestException("Unexpected block size.");
205 }
206
207
208 expand(mdPRF, mdPRFLen, secret, 0, secret.length, labelBytes,
209 seed, output, ipad, opad);
210
211 return output;
212 }
213
214 static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
215 byte[] seed, int outputLength) throws NoSuchAlgorithmException,
216 DigestException {
217 MessageDigest md5 = MessageDigest.getInstance("MD5");
218 MessageDigest sha = MessageDigest.getInstance("SHA1");
219 return doTLS10PRF(secret, labelBytes, seed, outputLength, md5, sha);
220 }
221
222 static byte[] doTLS10PRF(byte[] secret, byte[] labelBytes,
223 byte[] seed, int outputLength, MessageDigest md5,
224 MessageDigest sha) throws DigestException {
225
226
227
228
229
230
231
232
233
234
235
236
237
238 if (secret == null) {
239 secret = B0;
240 }
241 int off = secret.length >> 1;
242 int seclen = off + (secret.length & 1);
243
244 byte[] output = new byte[outputLength];
245
246
247 expand(md5, 16, secret, 0, seclen, labelBytes, seed, output,
248 HMAC_ipad64.clone(), HMAC_opad64.clone());
249
250
251 expand(sha, 20, secret, off, seclen, labelBytes, seed, output,
252 HMAC_ipad64.clone(), HMAC_opad64.clone());
253
254 return output;
255 }
256
257
258
259
260
261
262
263
264
265
266
267 private static void expand(MessageDigest digest, int hmacSize,
268 byte[] secret, int secOff, int secLen, byte[] label, byte[] seed,
269 byte[] output, byte[] pad1, byte[] pad2) throws DigestException {
270
271
272
273
274 for (int i = 0; i < secLen; i++) {
275 pad1[i] ^= secret[i + secOff];
276 pad2[i] ^= secret[i + secOff];
277 }
278
279 byte[] tmp = new byte[hmacSize];
280 byte[] aBytes = null;
281
282
283
284
285
286
287
288
289
290
291
292
293 int remaining = output.length;
294 int ofs = 0;
295 while (remaining > 0) {
296
297
298
299
300 digest.update(pad1);
301 if (aBytes == null) {
302 digest.update(label);
303 digest.update(seed);
304 } else {
305 digest.update(aBytes);
306 }
307 digest.digest(tmp, 0, hmacSize);
308
309
310 digest.update(pad2);
311 digest.update(tmp);
312 if (aBytes == null) {
313 aBytes = new byte[hmacSize];
314 }
315 digest.digest(aBytes, 0, hmacSize);
316
317
318
319
320
321 digest.update(pad1);
322 digest.update(aBytes);
323 digest.update(label);
324 digest.update(seed);
325 digest.digest(tmp, 0, hmacSize);
326
327
328 digest.update(pad2);
329 digest.update(tmp);
330 digest.digest(tmp, 0, hmacSize);
331
332 int k = Math.min(hmacSize, remaining);
333 for (int i = 0; i < k; i++) {
334 output[ofs++] ^= tmp[i];
335 }
336 remaining -= k;
337 }
338 }
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354 static public class V12 extends TlsPrfGenerator {
355 protected SecretKey engineGenerateKey() {
356 return engineGenerateKey0(true);
357 }
358 }
359
360
361
362
363 static public class V10 extends TlsPrfGenerator {
364 protected SecretKey engineGenerateKey() {
365 return engineGenerateKey0(false);
366 }
367 }
368 }